﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.ServiceModel.Syndication;
using System.Xml;
using System.Collections.ObjectModel;

namespace JaUtils
{
	public class RssReader
	{
		public static SyndicationFeed Read(Uri uri, string userName, string password, TextSyndicationContentKind contentKind)
		{
			var doc = new XmlDocument();
			doc.Load(uri.ToString());

			var rss = doc.DocumentElement;
			if (rss.Name != "rss")
				throw new FormatException("excepted 'rss' given '" + doc.DocumentElement.Name +"'");

			if ((rss.Attributes["version"] != null) && (rss.Attributes["version"].Value != "2.0"))
				throw new NotSupportedException("only rss 2.0 supported");

			var channel = rss.SelectSingleNode("channel");
			if (channel == null)
				throw new NotSupportedException("only feeds with exactly one channel are supported");


			var result = new SyndicationFeed();

			var title = channel.SelectSingleNode("title");
			if (title != null) result.Title = new TextSyndicationContent(title.InnerText);

			var links = channel.SelectNodes("link");
			foreach (XmlNode link in links)
				result.Links.Add(new SyndicationLink(new Uri(link.InnerText)));

			var descr = channel.SelectSingleNode("description");
			if (descr != null) result.Description = new TextSyndicationContent(title.InnerText);

			var lang = channel.SelectSingleNode("language");
			if (lang != null) result.Language = lang.InnerText;

			var generator = channel.SelectSingleNode("generator");
			if (generator != null) result.Generator = generator.InnerText;

			var managingEditor = channel.SelectSingleNode("managingEditor");
			if (managingEditor != null) result.Authors.Add(new SyndicationPerson(managingEditor.InnerText));

			var lastBuildDate = channel.SelectSingleNode("lastBuildDate");
			if (lastBuildDate != null) result.LastUpdatedTime = DateTime.Parse(lastBuildDate.InnerText);

			var image = channel.SelectSingleNode("image/url");
			if (image != null) result.ImageUrl = new Uri(image.InnerText);

			var item_list = new List<SyndicationItem>();
			var items = channel.SelectNodes("item");
			foreach (XmlNode item in items)
			{
				var cur_item = new SyndicationItem();

				var item_title = item.SelectSingleNode("title");
				if (item_title != null) cur_item.Title = new TextSyndicationContent(item_title.InnerText);

				var item_link = item.SelectSingleNode("link");
				if (item_link != null) cur_item.Links.Add(new SyndicationLink(new Uri(item_link.InnerText)));

				var description = item.SelectSingleNode("description");
				if (description != null) cur_item.Content = new TextSyndicationContent(description.InnerXml, contentKind);

				var pubDate = item.SelectSingleNode("pubDate");
				if (pubDate != null) cur_item.PublishDate = DateTimeOffset.Parse(pubDate.InnerText);

				var guid = item.SelectSingleNode("guid");
				if (guid != null) cur_item.Id = guid.InnerText;

				item_list.Add(cur_item);
			}

			result.Items = item_list;

			return result;
		}

		public static TextSyndicationContentKind FeedType(string typeName)
		{
			switch (typeName)
			{
			case "plaintext":
				return TextSyndicationContentKind.Plaintext;
			case "xhtml":
				return TextSyndicationContentKind.XHtml;
			case "html":
				return TextSyndicationContentKind.Html;
			default:
				throw new ArgumentException("typeName");
			}
		}
	}
}
